package com.neuedu.wemall.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.neuedu.wemall.common.util.MD5;
import com.neuedu.wemall.common.util.RandomCodeUtils;
import com.neuedu.wemall.common.util.SHAEncryptUtils;
import com.neuedu.wemall.common.vo.ResponseData;
import com.neuedu.wemall.dao.entity.Role;
import com.neuedu.wemall.dao.entity.UserRole;
import com.neuedu.wemall.service.IRoleService;
import com.neuedu.wemall.service.IUserRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.neuedu.wemall.dao.entity.User;
import com.neuedu.wemall.service.IUserService;
import com.neuedu.wemall.dao.mapper.UserMapper;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;


@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Autowired
    private IUserRoleService userRoleService;
    @Autowired
    private IRoleService roleService;

    @Override
    public Page<User> selectPageList(int pageNum, int pageSize, String keyword, User user) {
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        lqw.eq(User::getType, 2);//只查询普通用户
        if (StrUtil.isNotEmpty(keyword)) {
            lqw.and(wrapper ->
                    wrapper.eq(User::getEmpNo, keyword)
                            .or()
                            .eq(User::getMobile, keyword)
                            .or()
                            .eq(User::getName, keyword)
                            .or()
                            .eq(User::getEmail, keyword)
                            .or()
                            .eq(User::getIdCard, keyword));
        }
        Integer gender = user.getGender();
        if (gender != null && (1 == gender || 2 == gender)) {
            lqw.eq(User::getGender, gender);
        }
        Integer delStatus = user.getDelStatus();
        if (delStatus != null && (9 == delStatus || 1 == delStatus)) {
            lqw.eq(User::getDelStatus, delStatus);
        }
        Page<User> page = new Page<>(pageNum, pageSize);
        page = getBaseMapper().selectPage(page, lqw);
        List<User> userList = page.getRecords();
        if (CollectionUtil.isNotEmpty(userList)) {
            return page;
        }
        Map<Integer, String> roleMap = getRoleMap();
        for (User u : userList) {
            setUserRoles(u, roleMap);
        }
        return page;
    }

    private Map<Integer, String> getRoleMap() {
        Role roleTemplate = new Role();
        roleTemplate.setDelStatus(9);
        List<Role> roleList = roleService.selectRoleList(null, roleTemplate);
        //用户Map打包所有角色对象数据  key:角色ID;value:角色名称
        Map<Integer, String> roleMap = new HashMap<>();
        for (Role role : roleList) {
            int roleId = role.getId();
            String nameCn = role.getNameCn();
            roleMap.put(roleId, nameCn);
        }
        return roleMap;
    }

    ;

    /**
     * 设置用户角色
     *
     * @param user    用户对象
     * @param roleMap 角色Map
     */
    private void setUserRoles(User user, Map<Integer, String> roleMap) {
        //查询当前用户拥有的角色
        Integer userId = user.getId();
        if (userId == null) {
            return;
        }
        List<UserRole> userRoleList = userRoleService.selectUserRoleList(userId);
        if (CollectionUtil.isNotEmpty(userRoleList)) {
            List<Integer> roleIds = new ArrayList<>();
            List<String> roleNames = new ArrayList<>();
            for (UserRole userRole : userRoleList) {
                int roleId = userRole.getRoleId();
                roleIds.add(roleId);
                String roleNameZh = roleMap.get(roleId);
                roleNames.add(roleNameZh);
            }
            user.setRoleNames(roleNames);
            user.setRoleIds(roleIds);
        }
    }

    /**
     * 检查是否存在超级用户
     *
     * @return
     */
    private boolean exitsSupperUser() {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getType, 1);
        long count = getBaseMapper().selectCount(wrapper);
        return count > 0;
    }

    /**
     * 检查用户唯一字段是否重复
     *
     * @param user
     * @return
     */
    private boolean checkUniqueField(User user) {
        if (user == null) {
            return false;
        }
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        Integer userId = user.getId();
        if (userId != null) {
            lqw.ne(User::getId, userId);
        }
        String empNo = user.getEmpNo();
        String mobile = user.getMobile();
        String email = user.getEmail();
        String idCard = user.getIdCard();
        lqw.and(wrapper -> {
            if (StrUtil.isNotEmpty(empNo)) {
                wrapper.eq(User::getEmpNo, empNo);
                wrapper.or();
            }
            if (StrUtil.isNotEmpty(mobile)) {
                wrapper.eq(User::getMobile, mobile);
                wrapper.or();
            }
            if (StrUtil.isNotEmpty(email)) {
                wrapper.eq(User::getEmail, email);
                wrapper.or();
            }
            if (StrUtil.isNotEmpty(idCard)) {
                wrapper.eq(User::getIdCard, idCard);
            }
        });
        long count = getBaseMapper().selectCount(lqw);
        return count > 0;
    }

    /**
     * 密码加密
     *
     * @param password 密码
     * @param salt     盐值
     * @return 加密后的密码
     */
    private static String encryptPwd(String password, String salt) {
        String url = "https://wemall.seller.com/?salt={}&i={}&password={}";
        url = StrUtil.format(url, salt);
        for (int i = 1; i <= 150; i++) {
            String content = new String(url);
            content = StrUtil.format(content, i, password);
            password = SHAEncryptUtils.getSHA512(content);
        }
        for (int i = 1; i <= 150; i++) {
            String content = new String(url);
            content = StrUtil.format(content, i, password);
            password = MD5.getMD5(content);
        }
        return password;
    }

    @Override
    public User selectById(Integer userId) {
        User user = getBaseMapper().selectById(userId);
        if (user != null) {
            Map<Integer, String> roleMap = getRoleMap();
            setUserRoles(user, roleMap);
        }
        return user;
    }

    @Override
    public int deleteById(Integer userId) {
        User user = getBaseMapper().selectById(userId);
        if (user == null) {
            return 0;
        }
        if (1 == user.getType()) {
            //使用-1表示超级管理不可删除
            return -1;
        }
        return getBaseMapper().deleteById(userId);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public ResponseData insert(User user) {
        String empNo = user.getEmpNo();
        if (StrUtil.isEmpty(empNo)) {
            return ResponseData.missParam("员工编号");
        }
        Integer userType = user.getType();
        if (userType == null) {
            return ResponseData.missParam("用户类型");
        }
        String name = user.getName();
        if (StrUtil.isEmpty(name)) {
            return ResponseData.missParam("姓名");
        }
        String mobile = user.getMobile();
        if (StrUtil.isEmpty(mobile)) {
            return ResponseData.missParam("手机号");
        }
        String email = user.getEmail();
        if (StrUtil.isEmpty(email)) {
            return ResponseData.missParam("邮箱");
        }
        String idCard = user.getIdCard();
        if (StrUtil.isEmpty(idCard)) {
            return ResponseData.missParam("身份证号");
        }
        Integer gender = user.getGender();
        if (gender == null) {
            return ResponseData.missParam("性别");
        }
        if (!(1 == gender || 2 == gender)) {
            return ResponseData.createFail("性别状态错误【" + gender + "】");
        }
        if (!(1 == userType || 2 == userType)) {
            return ResponseData.createFail("用户类型错误【" + userType + "】");
        }
        if (1 == userType && exitsSupperUser()) {
            return ResponseData.createFail("系统已存在一个超级管理员");

        }
        if (checkUniqueField(user)) {
            return ResponseData.createFail("编号|手机号码|身份证号重复");
        }
        user.setType(userType);
        String salt = RandomCodeUtils.bulidRepeatCodes(64);
        user.setSalt(salt);
        //密码默认(加密后)身份证后八位
        String password = getDefaultPassword(idCard, salt);
        user.setPassword(password);
        user.setCreateTime(new Date());
        int rows = getBaseMapper().insert(user);
        return ResponseData.success(rows);
    }

    @Override
    public ResponseData modifyById(User user) {
        Integer userId = user.getId();
        if (userId == null) {
            return ResponseData.modifyFail("用户ID");
        }
        Integer delStatus = user.getDelStatus();
        if (!(delStatus == null || 1 == delStatus || 9 == delStatus)) {
            return ResponseData.modifyFail("用户状态错误【" + delStatus + "】");
        }
        if (checkUniqueField(user)) {
            return ResponseData.modifyFail("编号|手机号码|邮箱|身份证号重复");
        }
        user.setModifyTime(new Date());
        Integer type = user.getType();
        if (type != null) {
            return ResponseData.modifyFail("不可以修改用户类型");
        }
        String password = user.getPassword();
        if (StrUtil.isNotEmpty(password)) {
            return ResponseData.modifyFail("不可以修改密码");
        }
        String salt = user.getSalt();
        if (StrUtil.isEmpty(salt)) {
            return ResponseData.modifyFail("不可以修改盐值");
        }
        int rows = getBaseMapper().updateById(user);
        return ResponseData.success(rows);
    }

    @Override
    public ResponseData modifyPassword(String newPassword, String rePassword, String oldPassword, int userId) {
        if (StrUtil.isEmpty(newPassword)) {
            return ResponseData.missParam("新密码");
        }
        if (!newPassword.matches("^[\\S]{6,12}$")) {
            return ResponseData.modifyFail("新密码格式错误");
        }
        if (!newPassword.equals(rePassword)) {
            return ResponseData.modifyFail("新密码与确认密码不一致");
        }
        User user = getBaseMapper().selectById(userId);
        if (user == null) {
            return ResponseData.modifyFail("当前用户不存在");
        }
        String password = user.getPassword();//旧密码(加密后)
        String salt = user.getSalt();
        String encryptPwd = encryptPwd(oldPassword, salt);//修改密码页面输入的旧密码(加密后)
        if (!password.equals(encryptPwd)) {
            return ResponseData.modifyFail("旧密码输入有误");
        }
        if (newPassword.equals(oldPassword)) {
            return ResponseData.modifyFail("新密码与旧密码相同");
        }
        String idCard = user.getIdCard();
        String defaultPassword = getDefaultPassword(idCard);
        if (newPassword.equals(defaultPassword)) {
            return ResponseData.modifyFail("新密码不能与默认密码相同");
        }
        password = encryptPwd(newPassword, salt);//新密码(加密后)
        LambdaUpdateWrapper<User> luw = new LambdaUpdateWrapper<>();
        luw.set(User::getPassword, password);
        luw.set(User::getModifyTime, new Date());
        luw.eq(User::getId, userId);
        int rows = getBaseMapper().update(luw);
        return ResponseData.success(rows);
    }

    @Override
    public User loginUser(String account, String password) {
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        lqw.eq(User::getEmpNo, account);
        lqw.or();
        lqw.eq(User::getEmail, account);
        lqw.or();
        lqw.eq(User::getMobile, account);
        lqw.or();
        lqw.eq(User::getIdCard, account);
        User user = getBaseMapper().selectOne(lqw);
        if (user == null || user.getId() == null) {
            return null;
        }
        //原始密码
        String originPwd = user.getPassword();
        //将用户输入的密码进行加密
        String encryptPwd = encryptPwd(password, user.getSalt());
        if (!originPwd.equals(encryptPwd)) {
            //密码错误
            return null;
        }
        int delStatus = user.getDelStatus();
        if (9 == delStatus) {
            //用户已被删除或停用
            return user;
        }
        Map<Integer, String> roleMap = getRoleMap();
        setUserRoles(user, roleMap);
        return user;
    }

    @Override
    public int setUserRoles(int userId, int[] roleIds) {
        return 0;
    }

    @Override
    public long countSuperUser() {
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        lqw.eq(User::getType, 1);
        return getBaseMapper().selectCount(lqw);
    }

    @Override
    public boolean isDefaultPassword(User user) {
        String idCard = user.getIdCard();
        String password = user.getPassword();
        String salt = user.getSalt();
        String defaultPassword = getDefaultPassword(idCard, salt);
        return password.equals(defaultPassword);
    }

    /**
     * 获取加密后默认密码(身份证后八位)
     *
     * @param idCard 身份证号
     * @return
     */
    private String getDefaultPassword(String idCard, String salt) {
        if (StrUtil.isEmpty(idCard)) {
            throw new IllegalArgumentException("身份证号不能为空");
        }
        if (StrUtil.isEmpty(salt)) {
            throw new IllegalArgumentException("盐值不能为空");
        }
        String defaultPassword = getDefaultPassword(idCard);
        return encryptPwd(defaultPassword, salt);
    }

    /**
     * 获取加密前默认密码(身份证后八位)
     *
     * @param idCard 身份证号
     * @return
     */
    private String getDefaultPassword(String idCard) {
        if (StrUtil.isEmpty(idCard)) {
            throw new IllegalArgumentException("身份证号不能为空");
        }
        String defaultPassword = idCard.substring(idCard.length() - 8);
        return defaultPassword;
    }

}